package com.py.gs.businese.unionbattletest;

import java.util.ArrayList;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicInteger;

import com.py.gs.tools.NumberRandom;

public class UnionBattleService5 {
	
	int battleCount;
	
//	Random random = new Random();
//	Random random = new Random(156121324);//UnionBattleService1 块
//	Random random = new Random(156121320);//UnionBattleService1 慢
	static KRandom random = new KRandom(156121324);
	static NumberRandom rn = new NumberRandom(0, 500, new KRandom(154531321));
	
	ArrayList<UnionBattleInfo> unionBattles = new ArrayList<>();
	int defendNum;
	static ExecutorService threads = Executors.newFixedThreadPool(4);
	class UnionBattleInfo {
		long unionId;
		MinisterBattleInfo[] ministers;
		int winCount = 0;
		public UnionBattleInfo(long unionId, int ministerNum, int powerBound) {
			this.unionId = unionId;
			ministers = new MinisterBattleInfo[ministerNum];
			for (int i = 0; i < ministerNum; i++) {
				ministers[i] = new MinisterBattleInfo(i + 1, powerBound);
			}
		}
		
		@Override
		public String toString() {
			return "unionId:" + unionId + "_winCount:" + winCount;
		}
	}
	class MinisterBattleInfo {
		int ministerId;
		long initMinisterPower;
		long ministerLeftPower;
		int ministerWinCount = 0;
		public MinisterBattleInfo(int ministerId, int powerBound) {
			this.ministerId = ministerId;
			initMinisterPower = 100 + random.nextInt(powerBound);
			ministerLeftPower = initMinisterPower;
		}
		
		public void resetPower() {
			ministerLeftPower = initMinisterPower;
			ministerWinCount = 0;
		}
		
		@Override
		public String toString() {
			return "mId:" + ministerId + "_power:" + initMinisterPower;
		}
	}

	int[] targetIndex;
	/**
	 * 初始化联盟出战信息
	 * @param unionNum 联盟个数
	 * @param ministerNum 联盟出战大臣个数
	 * @param powerBound 军事势力浮动值
	 * 军事势力 = 基数100 + random.nextInt(powerBound)
	 */
	public UnionBattleService5(int unionNum, int ministerNum, int powerBound) {
//		System.out.println("初始化" + unionNum + "个战斗联盟");
		for (int i = 0; i < unionNum; i++) {
			UnionBattleInfo ubi = new UnionBattleInfo(i + 1, ministerNum, powerBound);
			unionBattles.add(ubi);
		}
//		System.out.println("初始化联盟出战信息...end");
	}
	
	public int battleParallel() throws InterruptedException {
//		System.out.println("联盟战斗测试");
		AtomicInteger winCount = new AtomicInteger();
		CountDownLatch cdl = new CountDownLatch(4);
		for (int j = 0; j < 4; j++) {
			int startIndex = j;
			threads.execute(()->{
				for (int i = startIndex; i < unionBattles.size(); i+=4) {
					UnionBattleInfo attack = unionBattles.get(i);
					battleRandomDefend1(attack);
	//				battleRandomDefend2(attack);
					winCount.addAndGet(attack.winCount);
				}
				cdl.countDown();
			});
		}
		cdl.await();
		unionBattles.sort((u1, u2)->Integer.compare(u1.winCount, u2.winCount));
		return winCount.get();
//		System.out.println("联盟战斗胜利次数榜单:" + unionBattles);
//		System.out.println("联盟战斗测试...end");
	}
	
	public int battle() {
//		System.out.println("联盟战斗测试");
		int winCount = 0;
		for (int i = 0; i < unionBattles.size(); i++) {
			UnionBattleInfo attack = unionBattles.get(i);
			battleRandomDefend1(attack);
//			battleRandomDefend2(attack);
			winCount += attack.winCount;
		}
		unionBattles.sort((u1, u2)->Integer.compare(u1.winCount, u2.winCount));
		return winCount;
//		System.out.println("联盟战斗胜利次数榜单:" + unionBattles);
//		System.out.println("联盟战斗测试...end");
	}
	private void battleRandomDefend1(UnionBattleInfo attack) {
		for (int j = 0; j < 100; j++) {
			UnionBattleInfo defend = null;
			int swapIdx = 0;
			do {
				swapIdx = rn.nextInt();
				defend = unionBattles.get(swapIdx);
			}while(defend==attack);
			if (battle(attack, defend)) {
				attack.winCount++;
			}else {
				break;
			}
		}
		rn.reset();
	}
	
	protected boolean battle(UnionBattleInfo attack, UnionBattleInfo defend) {
		if (attack.ministers.length == 0) {
			return false;
		}
		if (defend.ministers.length == 0) {
			return true;
		}
		int attackIndex = 0;
		int defendIndex = 0;
		MinisterBattleInfo attackMinister = attack.ministers[attackIndex];
		MinisterBattleInfo defendMinister = defend.ministers[defendIndex];
		while (true) {//打到自己活着对方没有出战大臣，停止战斗返回战斗结果
			int battleRet = battle(attackMinister, defendMinister);
			if (battleRet < 0) {//攻击方输
				attackMinister.resetPower();
				attackIndex++;
				if (attackIndex == attack.ministers.length) {
					defendMinister.resetPower();
					return false;
				}
				if (defendMinister.ministerWinCount < 2) {
					defendMinister.ministerWinCount++;
				} else {
					defendMinister.resetPower();
					defendIndex++;
					if (defendIndex == defend.ministers.length) {
						return true;
					}
					defendMinister = defend.ministers[defendIndex];
				}
				attackMinister = attack.ministers[attackIndex];
			} else if (battleRet > 0) {//防守方输
				defendMinister.resetPower();
				defendIndex++;
				if (defendIndex == defend.ministers.length) {
					attackMinister.resetPower();
					return true;
				}
				if (attackMinister.ministerWinCount < 2) {
					attackMinister.ministerWinCount++;
				} else {
					attackMinister.resetPower();
					attackIndex++;
					if (attackIndex == attack.ministers.length) {
						return false;
					}
					attackMinister = attack.ministers[attackIndex];
				}
				defendMinister = defend.ministers[defendIndex];
			} else {
				attackMinister.resetPower();
				defendMinister.resetPower();
				attackIndex++;
				if (attackIndex == attack.ministers.length) {
					return false;
				}
				defendIndex++;
				if (defendIndex == defend.ministers.length) {
					return true;
				}
				attackMinister = attack.ministers[attackIndex];
				defendMinister = defend.ministers[defendIndex];
			}
		}
	}
	/**
	 * 大臣战斗结果，小于0表示输，大于0表示赢，等于0表示一起死
	 * @param attackMinister
	 * @param defendMinister
	 * @return
	 */
	private int battle(MinisterBattleInfo attackMinister, MinisterBattleInfo defendMinister) {
		battleCount++;
		if (attackMinister.ministerLeftPower > defendMinister.ministerLeftPower) {
			attackMinister.ministerLeftPower -= defendMinister.ministerLeftPower;
			return 1;
		} else if (attackMinister.ministerLeftPower < defendMinister.ministerLeftPower) {
			defendMinister.ministerLeftPower -= attackMinister.ministerLeftPower;
			return -1;
		} else {
			return 0;
		}
	}
}
